/*
 * TestCasePanel.java
 *
 * Created on February 12, 2008, 2:39 AM
 */

package gui.testcase;

import datamodel.WSFOperation;
import datamodel.WSFResult;
import datamodel.WSFTestCase;
import gui.WSFApplication;
import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.border.TitledBorder;
import javax.swing.tree.DefaultTreeModel;
import org.apache.log4j.Logger;
import org.jdesktop.application.Action;
import org.jdesktop.application.Task;
import utils.JTreeUtils;

/**
 *
 * @author  chang
 */
public class TestCasePanel extends javax.swing.JPanel {
    
    private static Logger logger = Logger.getLogger(TestCasePanel.class);
    
    private WSFTestCase testCase;
    private int currentIndex;
    private DefaultListModel indexListModel;
    
    /** Creates new form TestCasePanel */
    public TestCasePanel(WSFTestCase testCase) {
        this.testCase = testCase;
        initComponents();
        
        postInit();
        
        showTestCase();
    }
    
    private void postInit(){
        indexList.setCellRenderer(new MyCellRenderer());
    }
    
    public void setTestCase(WSFTestCase testCase){
        this.testCase = testCase;
        showTestCase();
    }
    
    private void showTestCase(){
        WSFOperation operation = testCase.getOperation();
        
        indexListModel = new DefaultListModel();
        for(int i=0; i<testCase.getInputDataVector().size(); i++){
            indexListModel.addElement(i);
        }
        indexList.setModel(indexListModel);
        
        currentIndex = indexList.getSelectedIndex();
        if(currentIndex == -1)
            currentIndex = 0;
        
        DefaultTreeModel requestTreeModel = new DefaultTreeModel(testCase.getRequestTreeNode(currentIndex));
        requestTree.setModel(requestTreeModel);
        JTreeUtils.expandAll(requestTree, null);
        
        showResult(currentIndex);
        
        setButtons();
    }
    
    @Action
    public Task execute(){
        return executeTestCases(-1);
    }
    
    // set index to -1, to execute all 
    private Task executeTestCases(int index){
        
        logger.info("executeTestCase: "+testCase.getProject().getName()+"/"+testCase.getName() + " -- " + (index == -1 ? "ALL" : "index: "+index));
        
        ExecuteTestCase executeTestCase = new ExecuteTestCase(WSFApplication.getApplication(), testCase, index, this);
        testCase.setExecutor(executeTestCase);
        this.setButtons();
        return executeTestCase;
    }
    
    @Action
    public void stopExecuteTestCase(){
        logger.info("Try to stop the executing TestCase"+testCase.getName());
        testCase.getExecutor().cancel(true);
        testCase.setExecutor(null);
        setButtons();
    }
    
    @Action 
    public void clearExecution(){
        testCase.clearResults();
        this.setTestCase(testCase);
    }
    
    public void setButtons(){
        
        switch(testCase.getStatus()){
            
            case WSFTestCase.PRE_EXECUTION:
                executeButton.setEnabled(true);
                executeButton.setText("Execute");
                stopButton.setEnabled(false);
                clearButton.setEnabled(false);
                break;
                
            case WSFTestCase.EXECUTION:
                if(testCase.getExecutor() != null){     // now executing !
                    executeButton.setEnabled(false);
                    stopButton.setEnabled(true);
                    clearButton.setEnabled(false);
                }else{
                    executeButton.setEnabled(true);
                    executeButton.setText("Continue");
                    stopButton.setEnabled(false);
                    clearButton.setEnabled(true);
                }
                break;
            
            case WSFTestCase.FINISHED:
                executeButton.setEnabled(false);
                executeButton.setText("Execute");
                stopButton.setEnabled(false);
                clearButton.setEnabled(true);
                break;
        }
    }
    
    public void tryUpdateButtons(WSFTestCase testCase){
        if(this.testCase == testCase)
            setButtons();
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jToolBar1 = new javax.swing.JToolBar();
        executeButton = new javax.swing.JButton();
        stopButton = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JToolBar.Separator();
        clearButton = new javax.swing.JButton();
        jPanel2 = new javax.swing.JPanel();
        jSplitPane2 = new javax.swing.JSplitPane();
        jScrollPane2 = new javax.swing.JScrollPane();
        requestTree = new javax.swing.JTree();
        jSplitPane1 = new javax.swing.JSplitPane();
        jScrollPane3 = new javax.swing.JScrollPane();
        requestTextArea = new javax.swing.JTextArea();
        jScrollPane4 = new javax.swing.JScrollPane();
        responseTextArea = new javax.swing.JTextArea();
        jPanel1 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        indexList = new javax.swing.JList();

        setName("Form"); // NOI18N

        jToolBar1.setFloatable(false);
        jToolBar1.setRollover(true);
        jToolBar1.setName("jToolBar1"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(gui.WSFApplication.class).getContext().getActionMap(TestCasePanel.class, this);
        executeButton.setAction(actionMap.get("execute")); // NOI18N
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(gui.WSFApplication.class).getContext().getResourceMap(TestCasePanel.class);
        executeButton.setText(resourceMap.getString("executeButton.text")); // NOI18N
        executeButton.setFocusable(false);
        executeButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        executeButton.setName("executeButton"); // NOI18N
        executeButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(executeButton);

        stopButton.setAction(actionMap.get("stopExecuteTestCase")); // NOI18N
        stopButton.setText(resourceMap.getString("stopButton.text")); // NOI18N
        stopButton.setFocusable(false);
        stopButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        stopButton.setName("stopButton"); // NOI18N
        stopButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(stopButton);

        jSeparator1.setName("jSeparator1"); // NOI18N
        jToolBar1.add(jSeparator1);

        clearButton.setAction(actionMap.get("clearExecution")); // NOI18N
        clearButton.setText(resourceMap.getString("clearButton.text")); // NOI18N
        clearButton.setFocusable(false);
        clearButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        clearButton.setName("clearButton"); // NOI18N
        clearButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(clearButton);

        jPanel2.setName("jPanel2"); // NOI18N

        jSplitPane2.setDividerLocation(200);
        jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane2.setResizeWeight(0.2);
        jSplitPane2.setName("jSplitPane2"); // NOI18N
        jSplitPane2.setOneTouchExpandable(true);

        jScrollPane2.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jScrollPane2.border.title"))); // NOI18N
        jScrollPane2.setName("jScrollPane2"); // NOI18N

        requestTree.setName("requestTree"); // NOI18N
        requestTree.setRootVisible(false);
        jScrollPane2.setViewportView(requestTree);

        jSplitPane2.setTopComponent(jScrollPane2);

        jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane1.setResizeWeight(0.5);
        jSplitPane1.setMinimumSize(new java.awt.Dimension(300, 300));
        jSplitPane1.setName("jSplitPane1"); // NOI18N
        jSplitPane1.setOneTouchExpandable(true);

        jScrollPane3.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jScrollPane3.border.title"))); // NOI18N
        jScrollPane3.setName("jScrollPane3"); // NOI18N

        requestTextArea.setColumns(20);
        requestTextArea.setEditable(false);
        requestTextArea.setRows(5);
        requestTextArea.setName("requestTextArea"); // NOI18N
        jScrollPane3.setViewportView(requestTextArea);

        jSplitPane1.setTopComponent(jScrollPane3);

        jScrollPane4.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jScrollPane4.border.title"))); // NOI18N
        jScrollPane4.setName("jScrollPane4"); // NOI18N

        responseTextArea.setColumns(20);
        responseTextArea.setEditable(false);
        responseTextArea.setRows(5);
        responseTextArea.setName("responseTextArea"); // NOI18N
        jScrollPane4.setViewportView(responseTextArea);

        jSplitPane1.setRightComponent(jScrollPane4);

        jSplitPane2.setRightComponent(jSplitPane1);

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jPanel1.border.title"))); // NOI18N
        jPanel1.setMinimumSize(new java.awt.Dimension(66, 0));
        jPanel1.setName("jPanel1"); // NOI18N
        jPanel1.setLayout(new java.awt.GridLayout(0, 1));

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        indexList.setFont(resourceMap.getFont("indexList.font")); // NOI18N
        indexList.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "0", "10", "100", "1000", "10000", "100000", "1000000", "10000000", "99999999" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        indexList.setName("indexList"); // NOI18N
        indexList.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                indexListMouseClicked(evt);
            }
        });
        indexList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                indexListValueChanged(evt);
            }
        });
        jScrollPane1.setViewportView(indexList);

        jPanel1.add(jScrollPane1);

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 441, Short.MAX_VALUE))
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 509, Short.MAX_VALUE)
            .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 509, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jToolBar1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 537, Short.MAX_VALUE)
            .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void indexListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_indexListValueChanged

        // TODO add your handling code here:
        int index = indexList.getSelectedIndex();

        if(index == currentIndex){
            return;
        }
        
        if(index == -1)
            index = 0;
        
        showResult(index);
    }//GEN-LAST:event_indexListValueChanged

    private void indexListMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_indexListMouseClicked
        if(evt.getButton() == 1 && evt.getClickCount() == 2){
            if(testCase.getExecutor()!=null)
                return;
            
            Task task = executeTestCases(indexList.getSelectedIndex());
            task.execute();
        }
    }//GEN-LAST:event_indexListMouseClicked

    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton clearButton;
    private javax.swing.JButton executeButton;
    private javax.swing.JList indexList;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JToolBar.Separator jSeparator1;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JSplitPane jSplitPane2;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JTextArea requestTextArea;
    private javax.swing.JTree requestTree;
    private javax.swing.JTextArea responseTextArea;
    private javax.swing.JButton stopButton;
    // End of variables declaration//GEN-END:variables
    
    public void updateIndexList(WSFResult result){
        
        int index = result.getInputIndex();
        
        Object object = indexListModel.get(index);
        
        indexListModel.set(index, object);
        
        if(currentIndex == index){
            showResult(index);
        }
    }
    
    public void showResult(int index){
        currentIndex = index;
        
        if(indexList.getSelectedIndex() != index)
            indexList.setSelectedIndex(index);
        
        DefaultTreeModel requestTreeModel = new DefaultTreeModel(testCase.getRequestTreeNode(index));
        requestTree.setModel(requestTreeModel);
        JTreeUtils.expandAll(requestTree, null);
        
        WSFResult result = testCase.getResults().get(index);
        if(result.getInputIndex() == -1) {
            ((TitledBorder)jScrollPane4.getBorder()).setTitle("Response (Raw)");
            
            requestTextArea.setText("");
            responseTextArea.setText("");
            
            return;
        }
        requestTextArea.setText(result.getOutRaw());
        responseTextArea.setText(result.getInRaw());
        ((TitledBorder)jScrollPane4.getBorder()).setTitle("Response (Raw) -- Response Time: " + result.getTime() + " ms");
        jScrollPane4.repaint();
    }
    
    class MyCellRenderer extends DefaultListCellRenderer{
        
        final private Color colorForFinishedResultIndex = new Color(112,228,143);
        final private Color colorForNotPlaceHolderResultIndex = Color.WHITE;
        final private Color colorForNotFinishedResultIndex = new Color(226,108,114);
        final private Color colorForSelection = new Color(134,171,217);
        
        public MyCellRenderer(){
            super();
            setOpaque(true);
        }
        
        @Override
        public Component getListCellRendererComponent(JList list, Object object, int index, boolean isSelected, boolean isFocused){
            
            ArrayList<WSFResult> results = testCase.getResults();
            WSFResult result = results.get(index);
            
            setText(object.toString());
            
            if(isSelected){
                setBackground( colorForSelection );
                return this;
            }
            
            if(result.getStatus() == WSFResult.FINISHED){
                setBackground( colorForFinishedResultIndex );
            }else if(result.getStatus() == WSFResult.NOTFINISHED){
                setBackground( colorForNotFinishedResultIndex );
            }else{
                setBackground( colorForNotPlaceHolderResultIndex );
            }
            
            return this;
        }
    }
    
    public WSFTestCase getTestCase(){
        return this.testCase;
    }
    
}
